package com.woniu.cms.auth.core.service.impl;

import com.woniu.cms.auth.core.entity.RbacPerm;
import com.woniu.cms.auth.core.mapper.RbacPermMapper;
import com.woniu.cms.auth.core.service.IRbacPermService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.cms.auth.core.vo.CUPermVo;
import com.woniu.cms.auth.core.vo.PermVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lilili
 * @since 2022-09-16
 */
@Service
public class RbacPermServiceImpl extends ServiceImpl<RbacPermMapper, RbacPerm> implements IRbacPermService {
    @Resource
    private RbacPermMapper permMapper;

    /**
     * 获取所有权限之递归算法
     *  需要查询数据库多次，效率低
     * @return {@link List}<{@link PermVo}>
     */
    @Transactional
    @Override
    public List<PermVo> all() {
        List<PermVo> perms = new ArrayList<>();
        PermVo parent = new PermVo().setId(0);
        queryChildren(parent);
        return parent.getChildren();
    }

    void queryChildren(PermVo perm){
        List<PermVo> children = permMapper.getChildren(perm.getId());
        for (PermVo c : children) {
            queryChildren(c);
        }
        perm.setChildren(children);
    }


    /**
     * 获取所有权限之for循环
     *
     * @return {@link List}<{@link PermVo}>
     */
    @Transactional
    @Override
    public List<PermVo> all1() {
        List<PermVo> list = new ArrayList<>();
        //获取所有的权限
        List<PermVo> ps = permMapper.getAllPermVo();
        /**
         * 把所有的权限都当成子节点
         * 遇到pid为0的加入最终返回的数组
         * 如果pid不是0的话，就重新遍历全部权限，找到他的父节点并添加到父节点的children数组中
         * 其实时间复杂度也很高 差不多也是o(n方)
         */
        for (PermVo perm : ps) {
            PermVo children = perm;
            if(perm.getPid() == 0){
                list.add(perm);
            }else{
                for (PermVo inner : ps) {
                    if(children.getPid() == inner.getId()){
                        PermVo parent = inner;
                        parent.getChildren().add(children);
                    }

                }
            }
        }
        return list;
    }

    /**
     * 获取所有权限之for循环+map集合
     *  通过map集合在找父亲的时候将复杂度降为1
     *
     * @return {@link List}<{@link PermVo}>
     */
    @Transactional
    @Override
    public List<PermVo> all2() {
        List<PermVo> list = new ArrayList<>();
        //获取所有的权限
        List<PermVo> ps = permMapper.getAllPermVo();
        Map<Integer, PermVo> map = ps.stream().collect(Collectors.toMap(
                PermVo::getId, permVo -> permVo
        ));


        for (PermVo perm : ps) {
            PermVo children = perm;
            if(perm.getPid() == 0){
                list.add(perm);
            }else{
                PermVo parent = map.get(children.getPid());
                parent.getChildren().add(children);
            }
        }
        return list;
    }

    @Transactional
    @Override
    public boolean addPerm(CUPermVo permVo) {
        RbacPerm rbacPerm = new RbacPerm();
        rbacPerm.setTitle(permVo.getLabel());
        rbacPerm.setPid(permVo.getPid());
        rbacPerm.setUrl(permVo.getUrl());

        int insert = permMapper.insert(rbacPerm);
        if(insert == 0){
            throw new RuntimeException("添加权限失败");
        }
        return true;
    }

    @Transactional
    @Override
    public boolean updatePerm(CUPermVo permVo) {
        RbacPerm rbacPerm = new RbacPerm();
        rbacPerm.setId(permVo.getId());
        rbacPerm.setTitle(permVo.getLabel());
        rbacPerm.setUrl(permVo.getUrl());

        int update = permMapper.updateById(rbacPerm);
        if(update == 0){
            throw new RuntimeException("更新权限失败");
        }
        return true;
    }



    @Transactional
    @Override
    public boolean doAllot(Map<String, Object> map) {
        int i = permMapper.doAllot(map);
        if(i == 0){
            throw new RuntimeException("分配权限失败");
        }
        return true;
    }

    @Transactional
    @Override
    public boolean doUnAllot(Map<String, Object> map) {
        int i = permMapper.doUnAllot(map);
        if(i == 0){
            throw new RuntimeException("解除权限失败");
        }
        return true;
    }

    @Transactional
    @Override
    public List<PermVo> display(Integer roleId) {
        List<PermVo> list = new ArrayList<>();
        //获取所有的权限
        List<PermVo> ps = permMapper.getAllPermVo();
        //获取用户权限
        List<Integer> PermIds = permMapper.getAllPermIdByRoleId(roleId);
        //转成一个key为id，value为PermVo的map
        Map<Integer, PermVo> map = ps.stream().collect(Collectors.toMap(
                PermVo::getId, permVo -> permVo
        ));


        for (PermVo perm : ps) {
            if(PermIds.contains(perm.getId())){
                //如果权限包含在角色权限里，设置为选中，并重新放到map里
                perm.setChecked(true);
                map.put(perm.getId(), perm);
            }
            PermVo children = perm;
            if(perm.getPid() == 0){
                list.add(perm);
            }else{
                PermVo parent = map.get(children.getPid());
                parent.getChildren().add(children);
            }
        }
        return list;
    }


}
